package com.amao.ws.websocket.server;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.amao.ws.websocket.bean.Message;
import com.amao.ws.websocket.code.CustomClose;
import com.amao.ws.websocket.handler.CustomSendHandler;
import net.sf.json.JSONObject;

@Component
@ServerEndpoint(value = "/connect/{account}", configurator = WsConfigurator.class)
public class WsServer {

	public static Logger log = LoggerFactory.getLogger(WsServer.class);

	// 本机在线用户管理
	private static Map<String, Session> webSocketMap = new ConcurrentHashMap<String, Session>();

	private static synchronized int getWsSize() {
		return webSocketMap.size();
	}

	@OnOpen
	public void onOpen(@PathParam("account") String account, Session session, EndpointConfig config) {
		log.info("新连接：{}", account);
		try {
			if (webSocketMap.containsKey(account)) {
				webSocketMap.get(account).close(new CloseReason(new CustomClose(4003), "账号在其他地方登陆，你被强制掉线。"));
			}
			webSocketMap.put(account, session);
			log.info("onOpen:在线人数{}", getWsSize());

			for (String key : webSocketMap.keySet()) {
				if (!key.contentEquals(account)) {
					webSocketMap.get(key).getAsyncRemote().sendText(account + ":上线", new CustomSendHandler());
				}
			}

		} catch (Exception e) {
			log.error("打开 连接异常，账号：{}，异常信息：{}", account, e.getMessage());
		}
	}

	/**
	 * 接受字符流
	 * @param message
	 * @param session
	 * @param account
	 */
	@OnMessage
	public void onMessage(String message, Session session, @PathParam("account") String account) {

		try {
			log.info("收到文本信息：{}，账号：{}", message, account);
			JSONObject json = JSONObject.fromObject(message);
			Message msg = (Message) json.toBean(json, Message.class);

			for (String key : webSocketMap.keySet()) {
				if (!key.contentEquals(account)) {
					webSocketMap.get(key).getAsyncRemote().sendText(message, new CustomSendHandler());
				}
			}
		} catch (Exception e) {
			log.error("接收文本消息异常,账号：{}，异常信息{}", account, e.getMessage());
		}

	}

	/**
	 * 接收字节流，当所发送内容过大时会多次回调，使用boolean last判断是否发送完
	 * @param b
	 * @param last
	 * @param session
	 * @param account
	 */
	@OnMessage
	public void onMessage(byte[] b, boolean last, Session session, @PathParam("account") String account) {
		
	}

	@OnError
	public void onError(Session session, Throwable error, @PathParam("account") String account) {
		log.error("异常回调，账号：{}，异常信息：{}", account, error.getMessage());
	}

	@OnClose
	public void onClose(Session session, CloseReason closeReason, @PathParam("account") String account) {
		if (closeReason.getCloseCode().getCode() < 4000) {
			webSocketMap.remove(account);

			for (String key : webSocketMap.keySet()) {
				if (!key.contentEquals(account)) {
					webSocketMap.get(key).getAsyncRemote().sendText(account + ":掉线", new CustomSendHandler());
				}
			}

		}
		log.info("onClose:在线人数{}", getWsSize());

	}

}
